package com.example.a2032.Utils;

/**
 * @ClassName SerialPortUtil
 * @Description TODO
 * @Author sky
 * @Date 2020/11/30 0030 10:04
 * @Version 1.0
 */

import android.content.Context;
import android.util.Log;


import com.example.a2032.entity.ActionData;
import com.example.a2032.entity.BleData;
import com.yby.sensor.SensorJNI;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import android_serialport_api.SerialPort;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;

/**
 * 通过串口用于接收或发送数据
 */
public class SerialPortUtil {
    private static final SerialPortUtil ourInstance = new SerialPortUtil();
    private static final String TAG = "SerialPortUtil";
    private SerialPort mSerialPort = null;
    private InputStream inputStream = null;
    private OutputStream outputStream = null;
    private ReceiveThread mReceiveThread = null;
    private static boolean isStart = false;
    long lastDataTime = 0;

    public boolean isOpenSerialPort() {
        return isOpenSerialPort;
    }

    public void setOpenSerialPort(boolean openSerialPort) {
        isOpenSerialPort = openSerialPort;
    }

    boolean isOpenSerialPort;

    private SerialPortUtil() {

    }

    Context context;

    public void init(Context context) {
        this.context = context;
        //startTimer();
        openSerialPort();
    }

    public static SerialPortUtil getInstance() {

        return ourInstance;
    }

    /**
     * 打开串口，接收数据
     * 通过串口，接收单片机发送来的数据
     */
    public void openSerialPort() {
        try {
            mSerialPort = new SerialPort(new File("/dev/ttyS1"), 57600, 0);
            //调用对象SerialPort方法，获取串口中"读和写"的数据流
            inputStream = mSerialPort.getInputStream();
            outputStream = mSerialPort.getOutputStream();
            isStart = true;
            Log.e(TAG, "openSerialPort: >>mSerialPort==" + mSerialPort);
        } catch (IOException e) {
            e.printStackTrace();
        }
        getSerialPort();
        //  restartSerialPort();
    }

    /**
     * 关闭串口
     * 关闭串口中的输入输出流
     */
    public void closeSerialPort() {
        Log.i(TAG, "关闭串口");
        try {
            if (inputStream != null) {
                inputStream.close();
            }
            if (outputStream != null) {
                outputStream.close();
            }
//            mReceiveThread.destroy();
            isStart = false;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void sendData(byte[] value) {
        try {
            if (mSerialPort != null) {
//                if (!isOpenSerialPort) {
//                    restartSerialPort(value);
//                } else {
                outputStream.write(value);
                outputStream.flush();
                lastDataTime = System.currentTimeMillis();
                //}
                Log.e(TAG, "sendSerialPort: sendData== " + ResolveUtil.byte2Hex(value));

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void sendSerialPort(byte[] value) {
        if (!isStart) openSerialPort();
        if (isOpenSerialPort) {
            if (System.currentTimeMillis() - lastDataTime > 60000) isOpenSerialPort = false;
        }
        Log.i(TAG, "sendSerialPort: " + isOpenSerialPort);
        //每次通讯之前开一次串口(不这样做的话串口会经常不通讯)
        if (System.currentTimeMillis() - lastDataTime >10000) {
            restartSerialPort();
            Utils.startMeasureTimer(100, TimeUnit.MILLISECONDS, new Observer() {
                @Override
                public void onSubscribe(Disposable d) {

                }

                @Override
                public void onNext(Object o) {
                    sendData(value);
                }

                @Override
                public void onError(Throwable e) {

                }

                @Override
                public void onComplete() {

                }
            });
        } else {
            sendData(value);
        }


    }

    private void getSerialPort() {
        if (mReceiveThread == null) {
            mReceiveThread = new ReceiveThread();
        }
        mReceiveThread.start();
    }

    /**
     * 接收串口数据的线程
     */
    private class ReceiveThread extends Thread {
        @Override
        public void run() {
            super.run();
            while (isStart) {
                if (inputStream == null) {
                    return;
                }
                byte[] readData = new byte[1024];
                try {
                    int size = inputStream.read(readData);
                    if (size > 0) {
                        lastDataTime = System.currentTimeMillis();
                        // packageData(value);
                        byte[] value;
                        if (lengthTemp != 0) {
                            value = new byte[size + lengthTemp];
                            System.arraycopy(totalTempValue, 0, value, 0, lengthTemp);
                            System.arraycopy(readData, 0, value, lengthTemp, size);

                        } else {
                            value = new byte[size];
                            System.arraycopy(readData, 0, value, 0, size);
                        }
                        Log.i(TAG, "run: " + ResolveUtil.byte2Hex(value));
                        saveSleepData(value);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    byte[] totalTempValue;
    int index = 0;
    int bleLength = 0;
    List<byte[]> tempList = new ArrayList<>();
    int needLength = 0;


    private void packageData(byte[] value) {
        //第一个包
        int dataLength = value.length;
        if (ResolveUtil.checkHead(value)) {
            if (value.length <= 4) return;
            bleLength = ResolveUtil.getSingleValue(value[4]);
            //刚好是完整的一个包
            if (dataLength == bleLength + 6) {
                byte[] bleValue = new byte[bleLength];
                System.arraycopy(value, 5, bleValue, 0, bleLength);
                Log.i(TAG, "packageData: " + ResolveUtil.byte2Hex(bleValue));
                postData(bleValue);
            } else if (dataLength > bleLength + 6) {//这段数据是两个包或者更多
                byte[] bleValue = new byte[bleLength];
                System.arraycopy(value, 5, bleValue, 0, bleLength);
                postData(bleValue);
                byte[] lastValue = new byte[dataLength - (bleLength + 6)];
                System.arraycopy(value, bleLength + 6, lastValue, 0, lastValue.length);
                packageData(lastValue);
            } else {//这段数据不是个完整的包，剩下的数据在下一段数据
                totalTempValue = new byte[bleLength];
                int tempLength = dataLength - 5;
                System.arraycopy(value, 5, totalTempValue, 0, tempLength);
                index = tempLength;
            }
        } else {
            if (index != 0) {
                //收到完整的一包数据
                if (index + dataLength - 1 == bleLength) {
                    System.arraycopy(value, 0, totalTempValue, index, dataLength - 1);
                    index = 0;
                    Log.i(TAG, "packageData:1 " + ResolveUtil.byte2Hex(totalTempValue));
                    postData(totalTempValue);
                } else if (index + dataLength - 1 > bleLength) {
                    int needLength = bleLength - index;
                    System.arraycopy(value, 0, totalTempValue, index, needLength);
                    Log.i(TAG, "packageData: 不完整的包 " + ResolveUtil.byte2Hex(totalTempValue));
                    postData(totalTempValue);
                    int nextLength = dataLength - needLength - 1;
                    if (needLength == 0) return;
                    byte[] lastValue = new byte[nextLength];
                    System.arraycopy(value, needLength + 1, lastValue, 0, lastValue.length - 1);
                    index = 0;
                    packageData(lastValue);
                    Log.i(TAG, "packageData: 不完整的包 " + ResolveUtil.byte2Hex(lastValue));
                } else {
                    Log.i(TAG, "packageData: 小于");
                }
            }
        }
    }

    int lengthTemp = 0;

    private void saveSleepData(byte[] value) {
        lengthTemp = 0;
        int index = 0;
        int valueLength = value.length;
        if (valueLength < 4) return;
        int start = 0;
        while (index < valueLength) {
            //取出包头
            if (!ResolveUtil.checkHead(value, index)) {
                index++;
                continue;
            }
            if (valueLength <= index + 4) break;
            int dataLength = ResolveUtil.getSingleValue(value[index + 4]);
            if (valueLength <= index + 5 + dataLength) break;
            byte[] bleValue = new byte[dataLength];
            System.arraycopy(value, index + 5, bleValue, 0, bleValue.length);
            Log.i(TAG, "post " + ResolveUtil.byte2Hex(bleValue));
            //完整的一个数据包
            postData(bleValue);
            index += dataLength;
            start = index + 6;
            // contentLength=contentLength+dataLength+6;
        }
        int offset = valueLength - start;
        //Log.i(TAG, "data: "+valueLength+" "+start);
        //如果这个包还有多余的数据，剩下的数据放到下一个包前面
        if (offset != 0) {
            addTempValue(value, start == -1 ? 0 : start);
        }
        //   Log.i(TAG, "saveSleepData: break " + contentLength + " " + valueLength+" "+offset);
    }

    void addTempValue(byte[] value, int start) {
        Log.i(TAG, "addTempValue: start " + start);
        int valueLength = value.length;
        totalTempValue = new byte[valueLength - start];
        lengthTemp = totalTempValue.length;
        System.arraycopy(value, start, totalTempValue, 0, lengthTemp);
        Log.i(TAG, "addTempValue: temp " + ResolveUtil.byte2Hex(totalTempValue));
    }


    private void postData(byte[] value) {
//        initSerialPortStatus(value);
        BleData bleData = new BleData();
        bleData.setAction(ActionData.BleData);
        bleData.setValue(value);
        RxBus.getInstance().post(bleData);
        // SDUtil.saveBTLog( context,"2021.6.4", getEcgFormatTimeString(System.currentTimeMillis())+" receiver: "+ResolveUtil.byte2Hex(value));

    }

    public String getEcgFormatTimeString(long time) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
        return simpleDateFormat.format(new Date(time));
    }
//    void initSerialPortStatus(byte[] value) {
//        if (value[0] == DeviceConst.CMD_OpenSerialPort && value[1] == 1) {
//            isOpenSerialPort = value[2] == 1;
//        }
//    }

    /**
     * 串口为了省电会在一段时间没有数据通信后自动关闭
     * 再次发送数据需要先开启串口通信
     *
     * @param value
     */
    public void restartSerialPort(byte[] value) {
        SensorJNI.BT50Disable();
        Observable.timer(50, TimeUnit.MILLISECONDS).subscribe(new Consumer<Long>() {
            @Override
            public void accept(Long aLong) throws Exception {
                SensorJNI.BT50Enable();
                outputStream.write(value);
                outputStream.flush();
            }
        });
    }

    /**
     * 熄屏的时候要关闭串口，亮屏的时候开启
     * （Ecg测量延迟需要久点，此处50ms足够）
     */
    public void restartSerialPort(long delay) {
        Log.i(TAG, "restartSerialPort: " + delay);
        SensorJNI.BT50Disable();
        Observable.timer(delay, TimeUnit.MILLISECONDS).subscribe(new Consumer<Long>() {
            @Override
            public void accept(Long aLong) throws Exception {
                SensorJNI.BT50Enable();
               // isOpenSerialPort = true;
            }
        });
    }

    public void restartSerialPort() {
        restartSerialPort(50);
    }

    public void restartEcgSerialPort() {
        restartSerialPort(450);
    }
//    void startTimer(){
//        Observable.interval(1,TimeUnit.SECONDS).subscribe(new Observer<Long>() {
//            @Override
//            public void onSubscribe(Disposable d) {
//
//            }
//
//            @Override
//            public void onNext(Long aLong) {
//                SDUtil.saveBTLog( context,"2021.6.11", getEcgFormatTimeString(System.currentTimeMillis())+" count: "+aLong);
//            }
//
//            @Override
//            public void onError(Throwable e) {
//
//            }
//
//            @Override
//            public void onComplete() {
//
//            }
//        });
//    }
}
